package org.dtp.config;

import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
import org.springframework.boot.context.properties.source.MapConfigurationPropertySource;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.stereotype.Component;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.stream.Collectors;

/**
 * @ClassName DynamicThreadPoolProperties
 * @Description 动态线程池配置
 * @Author wangyiqi
 * @Date 2021-08-11-20:21
 **/
@Component
@ConfigurationProperties(prefix = "dynamic.threadpools")
public class DynamicThreadPoolProperties {

    /**
     * Nacos DataId, 监听配置修改用
     */
    private String nacosDataId;

    /**
     * Nacos Group, 监听配置修改用
     */
    private String nacosGroup;

    /**
     * Apollo的namespace, 监听配置修改用
     */
    private String apolloNamespace;

    /**
     * 刷新时间间隔，单位：ms
     */
    private int refreshTimeInterval = 1000;

    /**
     * 负责人
     */
    private String owner;

    /**
     * 线程池配置
     */
    private List<ThreadPoolProperties> executors = new ArrayList<>(10);

    public String getNacosDataId() {
        return nacosDataId;
    }

    public void setNacosDataId(String nacosDataId) {
        this.nacosDataId = nacosDataId;
    }

    public String getNacosGroup() {
        return nacosGroup;
    }

    public void setNacosGroup(String nacosGroup) {
        this.nacosGroup = nacosGroup;
    }

    public String getApolloNamespace() {
        return apolloNamespace;
    }

    public void setApolloNamespace(String apolloNamespace) {
        this.apolloNamespace = apolloNamespace;
    }

    public int getRefreshTimeInterval() {
        return refreshTimeInterval;
    }

    public void setRefreshTimeInterval(int refreshTimeInterval) {
        this.refreshTimeInterval = refreshTimeInterval;
    }

    public String getOwner() {
        return owner;
    }

    public void setOwner(String owner) {
        this.owner = owner;
    }

    public List<ThreadPoolProperties> getExecutors() {
        return executors;
    }

    public void setExecutors(List<ThreadPoolProperties> executors) {
        this.executors = executors;
    }

    /**
     * 刷新配置
     *
     * @param content 配置文件的内容
     */
    public void refresh(String content) {
        Properties properties = new Properties();
        try {
            properties.load(new ByteArrayInputStream(content.getBytes()));
            doRefresh(properties);
        } catch (IOException e) {
            throw new RuntimeException("refresh thread pool configuration exception", e);
        }
    }

    public void refreshYaml(String content) {
        YamlPropertiesFactoryBean bean = new YamlPropertiesFactoryBean();
        bean.setResources(new ByteArrayResource(content.getBytes(StandardCharsets.UTF_8)));
        Properties properties = bean.getObject();
        doRefresh(properties);
    }

    private void doRefresh(Properties properties) {
        Map<String, String> dataMap = properties.entrySet().stream().collect(
                Collectors.toMap(e -> e.getKey().toString(), e -> e.getValue().toString())
        );
        ConfigurationPropertySource sources = new MapConfigurationPropertySource(dataMap);

        Binder binder = new Binder(sources);
        binder.bind("dynamic.threadpools", Bindable.ofInstance(this)).get();
    }

}
